package com.yqg.protection.controller;


import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yqg.protection.common.Result;
import com.yqg.protection.common.interceptor.SysLog;
import com.yqg.protection.controller.dto.*;
import com.yqg.protection.entity.*;
import com.yqg.protection.mapper.*;
import com.yqg.protection.service.IClientService;
import com.yqg.protection.service.IEquipmentUnitService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ClientController 前端控制器
 *
 * @author zxf
 * @since 2024-07-24
 */
@RestController
@RequestMapping("/client")
@Slf4j
public class ClientController {

    @Resource
    private IClientService clientService;

    @Resource
    private UserMapper userMapper;

    @Autowired
    private ClientMapper clientMapper;

    @Autowired
    private EquipmentInputStoreMapper equipmentInputStoreMapper;

    @Autowired
    private WarnRecordMapper warnRecordMapper;

    @Resource
    private IEquipmentUnitService equipmentUnitService;

    @Autowired
    private RecordInspectionMapper recordInspectionMapper;

    @Autowired
    private RecordMaintenanceMapper recordMaintenanceMapper;

    @Autowired
    private InspectAddrCodeMapper inspectAddrCodeMapper;

    /**
     * 新增或者更新
     */
    @PostMapping("/edit")
    @SysLog("新增或者修改单位")
    public Result save(@RequestBody Client client) {
        if (client.getId() == null) {
            client.setState("0");
        }
        client.setIsDelete(0);
        log.info("client:" + client);
        return Result.success(clientService.saveOrUpdate(client));
    }

    /**
     * 删除
     */
    @GetMapping("delete/{id}")
    @SysLog("删除单位")
    public Result delete(@PathVariable Integer id) {
        Client client = clientService.getById(id);
        client.setIsDelete(1);
        return Result.success(clientService.saveOrUpdate(client));
    }

    /**
     * 查询所有
     */
    @GetMapping("/findMapByClient")
    public Result findAll(Integer level,
                          Long organizationId,
                          String isAllClient,
                          @RequestParam List<Long> clientIds) {
        List<MapDataDto> list = equipmentInputStoreMapper.findMapByClient(organizationId, level, isAllClient, clientIds);
        return Result.success(list);
    }

    /**
     * 根据id查询
     */
    @GetMapping("/{id}")
    public Result findOne(@PathVariable Integer id) {
        return Result.success(clientService.getById(id));
    }

    /**
     * 分页查询
     */
    @GetMapping("/page")
    public Result findPage(@RequestParam Integer pageNum,
                           @RequestParam Integer pageSize) {
        QueryWrapper<Client> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", 0);
        queryWrapper.orderByDesc("id");
        return Result.success(clientService.page(new Page<>(pageNum, pageSize), queryWrapper));
    }

    @GetMapping("/findChildClient")
    public Result findChildClient(Integer pageNum,
                                  Integer pageSize,
                                  String name,
                                  String address,
                                  Long pcId) {
        HashMap<String, Object> map = new HashMap<>();
        LambdaQueryWrapper<Client> clientLambdaQueryWrapper = new LambdaQueryWrapper<>();
        clientLambdaQueryWrapper.eq(Client::getPcId, pcId);
        if (name != null && !name.equals("")) {
            clientLambdaQueryWrapper.like(Client::getName, name);
        }
        if (address != null && !address.equals("")) {
            clientLambdaQueryWrapper.like(Client::getAddress, address);
        }
        if (pageNum != null) {
            Page<Client> clientPage = clientService.page(new Page<>(pageNum, pageSize), clientLambdaQueryWrapper);
            map.put("record", clientPage.getRecords());
            map.put("total", clientPage.getTotal());
        } else {
            List<Client> clientList = clientService.list(clientLambdaQueryWrapper);
            map.put("record", clientList);
            map.put("total", clientList.size());
        }
        return Result.success(map);
    }

    @GetMapping("/getSubordClient")
    public Result getSubordClient(Integer pageNum,
                                  Integer pageSize,
                                  Long userId,
                                  Integer level,
                                  Long organizationId,
                                  String isAllClient,
                                  String name,
                                  String address) {
        Integer pageNum1 = null;
        if (pageNum != null) {
            pageNum1 = pageSize * pageNum - pageSize;
        }
        HashMap<String, Object> map = new HashMap<>();
        if (isAllClient.equals("1")) {
            List<Long> clientIds1 = userMapper.getUserById(userId).getClientIds();
            LambdaQueryWrapper<Client> clientLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if (name != null && !name.equals("")) {
                clientLambdaQueryWrapper.like(Client::getName, name);
            }
            if (address != null && !address.equals("")) {
                clientLambdaQueryWrapper.like(Client::getAddress, address);
            }
            clientLambdaQueryWrapper.in(Client::getId, clientIds1);
            if (pageNum != null) {
                Page<Client> clientPage = clientService.page(new Page<>(pageNum, pageSize), clientLambdaQueryWrapper);
                map.put("record", clientPage.getRecords());
                map.put("total", clientPage.getTotal());
            } else {
                List<Client> clientList = clientService.list(clientLambdaQueryWrapper);
                map.put("record", clientList);
                map.put("total", clientList.size());
            }
        } else {
            List<Client> clients = clientMapper.getSubordClient(pageNum1, pageSize, organizationId, name, address, level);
            Long total = clientMapper.getSubordClientCount(organizationId, name, address, level);
            map.put("record", clients);
            map.put("total", total);
        }
        return Result.success(map);
    }


    @GetMapping("/listbyName")
    @ApiOperation("根据单位名称查询单位列表")
    public Result listbyName(String name,
                             Integer level,
                             Long organizationId,
                             String isAllClient,
                             @RequestParam List<Long> clientIds) {
        List<Client> clients = clientMapper.getClientsByName(organizationId, name, level, isAllClient, clientIds);
        return Result.success(clients);
    }

    @GetMapping("/listbyorgan")
    @ApiOperation("根据条件查询客户列表")
    public Result listbyorgan(@RequestParam Integer pageNum,
                              @RequestParam Integer pageSize,
                              Integer level,
                              Long organizationId,
                              String name,
                              String address,
                              String isAllClient,
                              @RequestParam List<Long> clientIds) {
        pageNum = pageSize * pageNum - pageSize;
        List<Client> clients = clientMapper.getClientsByOrganId(pageNum, pageSize, organizationId, name, address, level, isAllClient, clientIds);
        Long total = clientMapper.getClientsCountByOrganId(organizationId, name, address, level, isAllClient, clientIds);
        HashMap<String, Object> map = new HashMap<>();
        map.put("record", clients);
        map.put("total", total);
        return Result.success(map);
    }

    @GetMapping("/getMonitorkeyByEquip")
    @ApiOperation("根据设备ID查询物联云API密钥")
    public Result getMonitorkeyByEquip(Long equipmentInputStoreId) {
        return Result.success(clientMapper.getMonitorkeyByEquip(equipmentInputStoreId));
    }

    @GetMapping("/clientAndEquipCount")
    @ApiOperation("单位和设备统计")
    public Result clientAndEquipCount(Integer level,
                                      Long organizationId,
                                      String isAllClient,
                                      @RequestParam List<Long> clientIds) {
        Long clientsCount = clientMapper.getClientsCountByOrganId(organizationId, null, null, level, isAllClient, clientIds);
        List<Map<String, Object>> list = equipmentInputStoreMapper.findCountGroupByOnline(level, organizationId, isAllClient, clientIds);
        Long equipmentCount;
        Long onlineCount;
        String onlineRate;
        if (list.size() < 2) {
            if (list.get(0).get("online").equals("on")) {
                onlineRate = "100%";
                onlineCount = (Long) list.get(0).get("count");
            } else {
                onlineRate = "0%";
                onlineCount = 0L;
            }
        } else {
            if (list.get(0).get("online").equals("on")) {
                onlineCount = (Long) list.get(0).get("count");
            } else {
                onlineCount = (Long) list.get(1).get("count");
            }
            equipmentCount = (Long) list.get(0).get("count") + (Long) list.get(1).get("count");
            onlineRate = String.format("%.1f", ((onlineCount.doubleValue() / equipmentCount.doubleValue()) * 100)) + "%";
        }
        HashMap<String, Object> map = new HashMap<>();
        map.put("clientsCount", clientsCount);
        map.put("equipmentCount", onlineCount);
        map.put("onlineRate", onlineRate);
        return Result.success(map);
    }

    /**
     * 总体评分
     */
    @GetMapping("/overallScore")
    @ApiOperation("总体评分")
    public Result overallScore(Integer level,
                               Long organizationId,
                               String isAllClient,
                               @RequestParam List<Long> clientIds,
                               Long clientId) {
        Double score = clientMapper.overallScore(organizationId, level, isAllClient, clientIds, clientId);
        // score为null不判断，执行NumberUtil.round会报错
        if (score == null) {
            return Result.error("暂无评分数据");
        }
        return Result.success(NumberUtil.round(score * 100, 0));
    }

    @ApiOperation("查询PDF数据")
    @GetMapping("/findPdfData")
    public Result findPdfData(Long clientId,
                              String startTime,
                              String endTime) {
        Client client = clientService.getById(clientId);
        List<MouthDataDto> mouthDataDtoList = warnRecordMapper.findPdfMouthData(clientId, startTime, endTime);
        List<WarnRecord> warnRecordList = warnRecordMapper.selectPDFMouthlist(startTime, endTime, clientId);
        Map<Integer, List<WarnRecord>> collect = warnRecordList.stream().collect(Collectors.groupingBy(WarnRecord::getIsDeal));
        HashMap<Object, Object> map = new HashMap<>();
        map.put("total", warnRecordList.size());
        if (collect.get(1) != null) {
            map.put("processed", collect.get(1).size());
        } else {
            map.put("processed", 0);
        }
        if (collect.get(0) != null) {
            map.put("unprocessed", collect.get(0).size());
        } else {
            map.put("unprocessed", 0);
        }
        List<EquipmentInputStore> equipmentInputStoreList = equipmentInputStoreMapper.selectlist(0, 1l, "0", null, new ArrayList<>(), clientId);
        Integer equipmentCount = 0;
        LocalDateTime createTime = LocalDateTime.now();
        if (equipmentInputStoreList != null && equipmentInputStoreList.size() > 0) {
            equipmentCount = equipmentInputStoreList.size();
            createTime = equipmentInputStoreList.get(0).getStartTime();
        }
        Map<String, List<WarnRecord>> collect1 = warnRecordList.stream().collect(Collectors.groupingBy(WarnRecord::getWarnStateNum));
        Integer fireWarnCount = 0;
        Integer breakWarnCount = 0;
        Integer fireEquipmentCount = 0;
        Integer breakEquipmentCount = 0;
        String fireEquipmentScore = "0%";
        String breakEquipmentScore = "0%";
        if (collect1.get("1") != null) {
            List<WarnRecord> fireWarnRecords = collect1.get("1");
            fireWarnCount = fireWarnRecords.size();
            Map<String, List<WarnRecord>> collect2 = fireWarnRecords.stream().collect(Collectors.groupingBy(WarnRecord::getEquipmentId));
            fireEquipmentCount = collect2.size();
            fireEquipmentScore = NumberUtil.mul(NumberUtil.round((double)fireEquipmentCount / equipmentCount, 4), 100) + "%";
        }
        if (collect1.get("2") != null) {
            List<WarnRecord> fireWarnRecords = collect1.get("2");
            breakWarnCount = fireWarnRecords.size();
            Map<String, List<WarnRecord>> collect2 = fireWarnRecords.stream().collect(Collectors.groupingBy(WarnRecord::getEquipmentId));
            breakEquipmentCount = collect2.size();
            breakEquipmentScore = NumberUtil.mul(NumberUtil.round((double)breakEquipmentCount / equipmentCount, 4), 100) + "%";
        }
        List<WarnRecordCountDto> fireWarnRecordCountDtoList = warnRecordMapper.findWarnRecordCountDto(clientId, "1", startTime, endTime);
        List<WarnRecordCountDto> breakWarnRecordCountDtoList = warnRecordMapper.findWarnRecordCountDto(clientId, "2", startTime, endTime);
        Double score = clientMapper.overallScore(1l, 0, "0", new ArrayList<>(), clientId);
        BigDecimal clientScore;
        if (score == null) {
            clientScore = new BigDecimal(0);
        } else {
            clientScore = NumberUtil.round(score * 100, 0);
        }



        Integer recordCount = 0;
        Integer recordInspectionCount = 0;
        Integer recordMaintenanceCount = 0;
        QueryWrapper<RecordInspection> recordInspectionQueryWrapper = new QueryWrapper<>();
        recordInspectionQueryWrapper.eq("is_delete", 0);
        recordInspectionQueryWrapper.eq("client_id", clientId);
        recordInspectionQueryWrapper.between("date_time", startTime, endTime);
        List<RecordInspection> recordInspections = recordInspectionMapper.selectList(recordInspectionQueryWrapper);
        QueryWrapper<RecordMaintenance> recordMaintenanceQueryWrapper = new QueryWrapper<>();
        recordMaintenanceQueryWrapper.eq("is_delete", 0);
        recordMaintenanceQueryWrapper.eq("client_id", clientId);
        recordMaintenanceQueryWrapper.between("date_time", startTime, endTime);
        List<RecordMaintenance> recordMaintenances=  recordMaintenanceMapper.selectList(recordMaintenanceQueryWrapper);
        recordInspectionCount = recordInspections.size();
        recordMaintenanceCount = recordMaintenances.size();
        recordCount = recordInspectionCount + recordMaintenanceCount;

        LambdaQueryWrapper<InspectAddrCode> inspectAddrCodeQueryWrapper = new LambdaQueryWrapper<>();
        inspectAddrCodeQueryWrapper.eq(InspectAddrCode::getIsDelete, 0);
        inspectAddrCodeQueryWrapper.eq(InspectAddrCode::getClientId, clientId);
        inspectAddrCodeQueryWrapper.eq(InspectAddrCode::getIsPosition, "1");
        List<InspectAddrCode> inspectAddrCodes = inspectAddrCodeMapper.selectList(inspectAddrCodeQueryWrapper);

        Set<Long> recordInspectionAddrs = recordInspections.stream().filter(recordInspection -> !recordInspection.getState().equals("0")).map(RecordInspection::getAddress).collect(Collectors.toSet());
        String recordInspectionAddrScore = "0%";
        if (recordInspectionAddrs.size() > 0) {
            recordInspectionAddrScore = NumberUtil.mul(NumberUtil.round((double)recordInspectionAddrs.size() / inspectAddrCodes.size(), 4), 100) + "%";
        }
        List<RecordAddrDto> recordInspectionAddrDtoList = recordInspectionMapper.findRecordInspectionAddrDto(clientId, startTime, endTime);

        Set<Long> recordMaintenanceAddrs = recordMaintenances.stream().filter(recordMaintenance -> recordMaintenance.getState().equals("0")).map(RecordMaintenance::getAddress).collect(Collectors.toSet());
        String recordMaintenanceAddrScore = "0%";
        if (recordMaintenanceAddrs.size() > 0) {
            recordMaintenanceAddrScore = NumberUtil.mul(NumberUtil.round((double)recordMaintenanceAddrs.size() / inspectAddrCodes.size(), 4), 100) + "%";
        }
        List<RecordAddrDto> recordMaintenanceAddrDtoList = recordMaintenanceMapper.findRecordMaintenanceAddrDto(clientId, startTime, endTime);

        List<PdfMouthDataDto> pdfMouthDataDtos = recordMaintenanceMapper.findPdfMouthData(clientId, startTime, endTime);
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("clientName", client.getName());
        hashMap.put("clientAddress", client.getAddress());
        hashMap.put("clientTelephone", client.getTeleLinkman());
        hashMap.put("timePeriod", startTime.substring(0, 4) + "年" + startTime.substring(5, 7) + "月" + startTime.substring(8, 10) + "日至" + endTime.substring(0, 4) + "年" + endTime.substring(5, 7) + "月" + endTime.substring(8, 10) + "日");
        hashMap.put("equipmentCount", equipmentCount);
        hashMap.put("equipmentUnitCount", equipmentCount);
        hashMap.put("createTime", createTime);

        hashMap.put("clientScore", clientScore);
        hashMap.put("processedWarnMap", map);

        hashMap.put("warnRecordCount", warnRecordList.size());
        hashMap.put("fireWarnCount", fireWarnCount);
        hashMap.put("breakWarnCount", breakWarnCount);
        //两个柱状图的数据
        hashMap.put("warnMouthData", mouthDataDtoList);

        hashMap.put("fireEquipmentUnitCount", fireEquipmentCount);
        hashMap.put("fireEquipmentUnitScore", fireEquipmentScore);
        //报警风险点
        hashMap.put("fireWarnRecordCountDtoList", fireWarnRecordCountDtoList);

        hashMap.put("breakEquipmentUnitCount", breakEquipmentCount);
        hashMap.put("breakEquipmentUnitScore", breakEquipmentScore);
        hashMap.put("breakWarnRecordCountDtoList", breakWarnRecordCountDtoList);

        hashMap.put("recordCount", recordCount);
        hashMap.put("recordInspectionCount", recordInspectionCount);
        hashMap.put("recordMaintenanceCount", recordMaintenanceCount);

        hashMap.put("recordAddrCount", inspectAddrCodes.size());

        hashMap.put("pdfMouthDataDtos", pdfMouthDataDtos);

        hashMap.put("recordInspectionAddrCount", recordInspectionAddrs.size());
        hashMap.put("recordInspectionAddrScore", recordInspectionAddrScore);
        hashMap.put("recordInspectionAddrDtoList", recordInspectionAddrDtoList);

        hashMap.put("recordMaintenanceAddrCount", recordMaintenanceAddrs.size());
        hashMap.put("recordMaintenanceAddrScore", recordMaintenanceAddrScore);
        hashMap.put("recordMaintenanceAddrDtoList", recordMaintenanceAddrDtoList);
        return Result.success(hashMap);
    }

    @ApiOperation("导出数据")
    @GetMapping("/export")
    public void export(HttpServletResponse response,
                       Integer level,
                       Long organizationId,
                       String name,
                       String address,
                       String isAllClient,
                       @RequestParam List<Long> clientIds) {
        clientService.export(response, organizationId, name, address, level, isAllClient, clientIds);
    }

    @ApiOperation("导入数据")
    @PostMapping("/importData")
    @SysLog("导入单位")
    public void importData(MultipartFile file) {
        clientService.importData(file);
    }
}

